package com.amadeus.spin.devtool.soap.shooter.process;

import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;

import com.amadeus.spin.devtool.soap.shooter.FatalException;
import com.amadeus.spin.devtool.soap.shooter.ProcessInput;
import com.amadeus.spin.devtool.soap.shooter.Shooter;
import com.amadeus.spin.standard.util.XPathHelper;

public class Replace implements ProcessInput {
  private static Logger log = Logger.getLogger(Replace.class);

  @Override
  public String processInput(Stack<String> previousOutputs, String input, Node config) throws FatalException {
    List<String> keys = XPathHelper.getProperties(config, "entry/@key");
    List<String> values = XPathHelper.getProperties(config, "entry/@value");

    for (int i = 0; i < keys.size(); i++) {
      String key = keys.get(i);
      String value = Shooter.replaceVariables(values.get(i));

      // Match elements within tags but get repeated groups
      String escapedKey = Pattern.quote(key);
      Pattern xmlElement = Pattern.compile("<" + escapedKey + ">((?:(?!</" + escapedKey + ">).)*)</" +
          escapedKey + ">", Pattern.DOTALL);
      Pattern xmlEmptyElement = Pattern.compile("<\\s*" + escapedKey + "\\s*/\\s*>", Pattern.DOTALL);
      Matcher mXmlElement = xmlElement.matcher(input);

      // to process a standard node <key>xxx</key>
      if (mXmlElement.find()) {
        StringBuffer buffer = new StringBuffer();
        log.info("setting " + key + " = " + value + " (old value : '" + mXmlElement.group(1) + "')");
        mXmlElement.reset();
        while (mXmlElement.find()) {
          mXmlElement.appendReplacement(buffer, "<" + key + ">" + value + "</" + key + ">");
        }
        mXmlElement.appendTail(buffer);
        input = buffer.toString();
      }
      Matcher mXmlEmptyElement = xmlEmptyElement.matcher(input);
      if (mXmlEmptyElement.find()) { // to process a compact node <key/>
        StringBuffer buffer = new StringBuffer();
        log.info("setting " + key + " = " + value + " (old value :'')");
        mXmlEmptyElement.reset();
        while (mXmlEmptyElement.find()) {
          mXmlEmptyElement.appendReplacement(buffer, "<" + key + ">" + value + "</" +
              key + ">");
        }
        mXmlEmptyElement.appendTail(buffer);
        input = buffer.toString();
      }
    }

    return input;
  }
}